//
//  UIView+Util.m
//  Melinked
//
//  Created by peter on 15/4/2.
//  Copyright (c) 2015年 YEL. All rights reserved.
//

#import "UIView+Util.h"
#import <objc/runtime.h>
#import <objc/message.h>

static const char *kTapGestureRecognizerBlockAddress;
static const char *kObserViewConstrollerAddress;
static const char *kYCoordinateOffsetAddress;
static const char *kMarkedValueAddress;
static const char *kMaskOpacityLayerAddress;

static id KeyBoardFrameDidChangeNotificationHandler = nil,KeyBoardFrameDidHideNotificationHandler = nil;
@implementation UIView (YWUtil)
//+ (void)load {
//    
//    Class class = [self class];
//    SEL originBoundsSEL = @selector(bounds);
//    SEL overrideBoundsSEL = @selector(overrideBounds);
//    Method originBoundsMethod = class_getInstanceMethod(class, originBoundsSEL),
//    overrideBoundsMethod = class_getInstanceMethod(class, overrideBoundsSEL);
//    if(class_addMethod(class, overrideBoundsSEL, method_getImplementation(originBoundsMethod), method_getTypeEncoding(originBoundsMethod))) {
//        class_replaceMethod(class, originBoundsSEL, method_getImplementation(overrideBoundsMethod), method_getTypeEncoding(overrideBoundsMethod));
//    }else {
//        method_exchangeImplementations(originBoundsMethod, overrideBoundsMethod);
//    }
//}
//
//- (CGRect)overrideBounds {
//    [self layoutIfNeeded];
//    return [self overrideBounds];
//}

- (UIViewController *)nearestViewController {
    
    UIViewController *nearestViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    while (nearestViewController.presentedViewController) {
        nearestViewController = nearestViewController.presentedViewController;
    }
    return nearestViewController;
}

- (void)setMarked:(BOOL)marked {
    objc_setAssociatedObject(self, &kMarkedValueAddress, @(marked), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (BOOL)isMarked {
    return [objc_getAssociatedObject(self, &kMarkedValueAddress) boolValue];
}

- (void)setHeight:(CGFloat)height {
    CGRect frame = self.frame;
    frame.size.height = height;
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.frame = frame;
//    });
}

- (void)setWidth:(CGFloat)width {
    CGRect frame = self.frame;
    frame.size.width = width;
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    
        self.frame = frame;
//    });
}

- (CGFloat)width {
    return CGRectGetWidth(self.frame);
}

- (CGFloat)height {
    return CGRectGetHeight(self.frame);
}

- (void)setX:(CGFloat)x {
    CGRect rect = self.frame;
    rect.origin.x = x;
    self.frame = rect;
}

- (void)setY:(CGFloat)y {
    CGRect rect = self.frame;
    rect.origin.y = y;
    self.frame = rect;
    
}

- (CGFloat)x {
    return CGRectGetMinX(self.frame);
}

- (CGFloat)y {
    return CGRectGetMinY(self.frame);
}

- (void)setOffsetYWithDistance:(CGFloat)distance {
    objc_setAssociatedObject(self, &kYCoordinateOffsetAddress, @(distance), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (CGFloat)offsetYDistance {
    return [objc_getAssociatedObject(self, &kYCoordinateOffsetAddress) floatValue];
}

- (UIViewController *)addObserViewConstroller {
    return objc_getAssociatedObject(self, &kObserViewConstrollerAddress);
}

- (void)setAddObserViewConstroller:(UIViewController *)addObserViewConstroller {
    if(addObserViewConstroller == nil) {
        return;
    }
    if([self isKindOfClass:[UITextField class]] || [self isKindOfClass:[UITextView class]]) {
        objc_setAssociatedObject(self, &kObserViewConstrollerAddress, addObserViewConstroller, OBJC_ASSOCIATION_RETAIN);
        KeyBoardFrameDidHideNotificationHandler = [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillHideNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
            if(!self.isFirstResponder) {
                return;
            }
            if([self offsetYDistance] > 0) {
                return;
            }
            NSValue *animationDurationValue = [[note userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey];
            NSTimeInterval animationDuration;
            [animationDurationValue getValue:&animationDuration];
            CGRect frame = addObserViewConstroller.view.frame;
            frame.origin.y = [self viewConstrollTopHeight];
            [UIView animateWithDuration:animationDuration animations:^{
                addObserViewConstroller.view.frame = frame;
            }];
        }];
        KeyBoardFrameDidChangeNotificationHandler = [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
            //    是否当前响应是自己
            if(!self.isFirstResponder) {
                return;
            }
            double boardHeight = [[[note userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
            NSValue *animationDurationValue = [[note userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey];
            NSTimeInterval animationDuration;
            [animationDurationValue getValue:&animationDuration];
            CGPoint point =  [self convertPoint:CGPointMake(0, CGRectGetHeight(self.frame)) toView:addObserViewConstroller.view];
            CGFloat windowHeight = CGRectGetHeight(addObserViewConstroller.view.frame);
            CGFloat recordManyDistance = windowHeight - point.y - boardHeight;
            [self setOffsetYWithDistance:recordManyDistance];
            CGRect frame = addObserViewConstroller.view.frame;
            if(recordManyDistance > 0) {
                return;
            }
            frame.origin.y = recordManyDistance + [self viewConstrollTopHeight];
            [UIView animateWithDuration:animationDuration animations:^{
                addObserViewConstroller.view.frame = frame;
            }];
        }];
    }
}

- (void)setCornerRadius:(float)cornerRadius {
    self.layer.cornerRadius = cornerRadius;
    self.layer.masksToBounds = YES;
}

- (float)cornerRadius {
    return self.layer.cornerRadius;
}

- (CGFloat)viewConstrollTopHeight {
    return self.addObserViewConstroller.navigationController.navigationBar.translucent ? 0 : self.addObserViewConstroller.navigationController.navigationBarHidden ? 20 : 64;
}

- (void)clearSubViews {
    for (UIView *subView in self.subviews) {
        [subView removeFromSuperview];
    }
}

- (void)configureRound {
    self.layer.cornerRadius = CGRectGetHeight(self.frame) / 2;
    self.layer.masksToBounds = YES;
}

CGFloat converResolutionWithDistance(CGFloat distanceFloat) {
    return distanceFloat / [[UIScreen mainScreen] scale];
}

- (void)reLayout:(CGSize)size {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:size.width],
    *heightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:size.height];
    [self addConstraints:@[widthConstraint,heightConstraint]];
    [self setNeedsUpdateConstraints];
    [self updateConstraints];
}

- (void)reLayoutByWidth:(CGFloat)distance {
    [self reLayout:CGSizeMake(converResolutionWithDistance(distance), CGRectGetHeight(self.frame))];
}

- (void)reLayoutByHeight:(CGFloat)distance {
    [self reLayout:CGSizeMake(CGRectGetWidth(self.frame), converResolutionWithDistance(distance))];
}

- (void)tapUpWithBlock:(void(^)(UIView *))aBlock {
    if(aBlock) {
        self.tapAction = aBlock;
        self.userInteractionEnabled = YES;
        UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapSelfTargetAction)];
        [self addGestureRecognizer:tapGestureRecognizer];
    }
}

- (void)setTapAction:(void (^)(UIView *))tapAction {
    objc_setAssociatedObject(self, &kTapGestureRecognizerBlockAddress, tapAction, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (void(^)(UIView *))tapAction {
    return objc_getAssociatedObject(self, &kTapGestureRecognizerBlockAddress);
}


- (void)tapSelfTargetAction {
    id block = objc_getAssociatedObject(self, &kTapGestureRecognizerBlockAddress);
    if(!block){
        return;
    }
    void(^touchUpBlock)(UIView *) = block;
    touchUpBlock(self);
}

- (void)reSetXCoords:(CGFloat)aCoords {
    CGRect rect = self.frame;
    rect.origin.x = aCoords;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.frame = rect;
    });
}

- (void)reSetYCoords:(CGFloat)aCoords {
    CGRect rect = self.frame;
    rect.origin.y = aCoords;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.frame = rect;
    });
}

- (void)roundRadiusWithCorners:(UIRectCorner)corners radius:(CGFloat)radius fillColor:(UIColor *)fillColor strokeColor:(UIColor *)strokeColor {
    
    CGRect bounds = self.bounds;
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds
                                                   byRoundingCorners:corners
                                                         cornerRadii:CGSizeMake(radius, radius)];
    
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.fillColor = fillColor.CGColor;
    maskLayer.strokeColor = strokeColor.CGColor;
    maskLayer.frame = bounds;
    maskLayer.lineWidth = 1;
    maskLayer.lineJoin = kCALineCapRound;
    maskLayer.path = maskPath.CGPath;
    [self.layer addSublayer:maskLayer];
}

- (void)rider_drawCornersRadius:(CGFloat)radius roundCorners:(UIRectCorner)corners {
    CGRect bounds = self.bounds;
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds
                                                   byRoundingCorners:corners
                                                         cornerRadii:CGSizeMake(radius, radius)];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    maskLayer.frame = bounds;
    maskLayer.path = maskPath.CGPath;
    self.layer.mask = maskLayer;
}

- (void)roundBorderWithBorderDirection:(BorderDirectionMark)direction lineWidth:(CGFloat)lineWidth color:(UIColor *)color {
    if(direction == BorderDirectionALL) {
        self.layer.borderWidth = lineWidth;
        self.layer.borderColor = color.CGColor;
        return;
    }
    
    if(direction & BorderDirectionTop) {
        CALayer *border = [CALayer layer];
        border.backgroundColor = color.CGColor;
        border.frame = CGRectMake(0, 0,  CGRectGetWidth(self.frame) ,lineWidth);
        [self.layer addSublayer:border];
    }
    
    if(direction & BorderDirectionLeft) {
        CALayer *border = [CALayer layer];
        border.backgroundColor = color.CGColor;
        border.frame = CGRectMake(0, 0, lineWidth,CGRectGetHeight(self.frame));
        [self.layer addSublayer:border];
    }
    
    if(direction & BorderDirecionBottom) {
        CALayer *border = [CALayer layer];
        border.backgroundColor = color.CGColor;
        border.frame = CGRectMake(0, CGRectGetHeight(self.frame) - lineWidth, CGRectGetWidth(self.frame), lineWidth);
        [self.layer addSublayer:border];
    }
    
    if(direction & BorderDirectionRight) {
        CALayer *border = [CALayer layer];
        border.backgroundColor = color.CGColor;
        border.frame = CGRectMake(CGRectGetWidth(self.frame) - lineWidth, 0,lineWidth,  CGRectGetHeight(self.frame));
        [self.layer addSublayer:border];
    }
}

- (CALayer *)maskOpacityLayer {
    return objc_getAssociatedObject(self, &kMaskOpacityLayerAddress)?:^{
        CALayer *maskOpactityLayer = [[CALayer alloc] init];
        maskOpactityLayer.frame = self.bounds;
        [self.layer addSublayer:maskOpactityLayer];
        objc_setAssociatedObject(self, &kMaskOpacityLayerAddress, maskOpactityLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        return maskOpactityLayer;
    }();
}


- (void)showLoadingView {
    MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:self];
    hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
    hud.bezelView.backgroundColor = [UIColor blackColor];
    hud.removeFromSuperViewOnHide = YES;
    [UIActivityIndicatorView appearanceWhenContainedIn:[MBProgressHUD class], nil].color = [UIColor whiteColor];
    [self addSubview:hud];
    [hud showAnimated:YES];
}

- (void)hiddenLoadingView {
    [MBProgressHUD hideHUDForView:self animated:YES];
}

@end
